package com.mall.test.address;

import sun.misc.Unsafe;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
 * @Author: Sam
 * @Date: 2022-02-09 17:05
 * @Description: 各种方式创建对象的内存地址是否一致
 */
public class aa {

    static final Unsafe unsafe = getUnsafe();
    static final boolean is64bit = true; // auto detect if possible.

    public static void main(String[] args) {
        Earth a = Earth.getInstance();

        //GC前
        System.out.println("-----------GC前------------");
        print(a);

        System.gc();

        //GC后
        System.out.println("-----------GC后------------");
        print(a);

        System.out.println("--------------------------");

        Earth beanA = Earth.getInstance();
        Earth beanB = Earth.getInstance();
        //利用反射调用私有构造方法
        try {
            Class classes = Class.forName(Earth.class.getName());
            Constructor[] declaredConstructors = classes.getDeclaredConstructors();
            for (Constructor declaredConstructor : declaredConstructors) {
                declaredConstructor.setAccessible(true);
                Earth beanC = (Earth) declaredConstructor.newInstance();
                System.out.println(beanA.hashCode());
                System.out.println(beanB.hashCode());
                System.out.println(beanC.hashCode());
                System.out.println("A equals B = " + (beanA.hashCode() == beanB.hashCode()));
                System.out.println("A equals C = " + (beanA.hashCode() == beanC.hashCode()));
                System.out.println("--------------------------");
                print(beanA);
                System.out.println("--------------------------");
                print(beanB);
                System.out.println("--------------------------");
                print(beanC);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void print(Earth a) {
        // hashcode
        System.out.println("Hashcode :       " + a.hashCode());
        System.out.println("Hashcode :       " + System.identityHashCode(a));
        System.out.println("Hashcode (HEX) : " + Integer.toHexString(a.hashCode()));// Integer.toHexString(int)是将一个整型转成一个十六进制数

        // toString
        System.out.println("toString :       " + a);

        //通过sun.misc.Unsafe;
        printAddresses("Address", a);
    }

    @SuppressWarnings("deprecation")
    public static void printAddresses(String label, Object... objects) {
        System.out.print(label + ":         0x");
        long last = 0;
        int offset = unsafe.arrayBaseOffset(objects.getClass());
        int scale = unsafe.arrayIndexScale(objects.getClass());
        switch (scale) {
            case 4:
                long factor = is64bit ? 8 : 1;
                final long i1 = (unsafe.getInt(objects, offset) & 0xFFFFFFFFL) * factor;
                System.out.print(Long.toHexString(i1));
                last = i1;
                for (int i = 1; i < objects.length; i++) {
                    final long i2 = (unsafe.getInt(objects, offset + i * 4) & 0xFFFFFFFFL) * factor;
                    if (i2 > last)
                        System.out.print(", +" + Long.toHexString(i2 - last));
                    else
                        System.out.print(", -" + Long.toHexString(last - i2));
                    last = i2;
                }
                break;
            case 8:
                throw new AssertionError("Not supported");
        }
        System.out.println();
    }

    private static Unsafe getUnsafe() {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            return (Unsafe) theUnsafe.get(null);
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}
